﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Red.GameData
{
    /// <summary>
    /// View handler for the object's property
    /// </summary>
    public partial class EditorPropertyView
    {
        /// <summary>
        /// Object this property view was created for
        /// </summary>
        public EditorObjectView Object { get; private set; }

        /// <summary>
        /// Reflection system property information
        /// </summary>
        public Raw.ReflectionProperty ReflectionProp { get; private set; }

        /// <summary>
        /// Array edition - valueID of the element to display
        /// Used for array where the displayable elements are always bounded with the specific named values
        /// NOTE: not set for normal properties
        /// </summary>
        public Guid ValueID { get; private set; }

        /// <summary>
        /// Array edition - parent property (used as a cache of values)
        /// NOTE: not set for normal properties
        /// </summary>
        public EditorPropertyView ParentProp { get; private set; }

        /// <summary>
        /// Get the reflection type for this property
        /// </summary>
        public Raw.ReflectionType ReflectionType
        {
            get
            {
                return ReflectionProp.Type;
            }
        }

        /// <summary>
        /// Get name of the property being edited
        /// </summary>
        public string Name
        {
            get
            {
                return ReflectionProp.Name;
            }
        }

        /// <summary>
        /// Display category for this property
        /// </summary>
        public string Category
        {
            get
            {
                return ReflectionProp.Category;
            }
        }

        /// <summary>
        /// Is this property considered final?
        /// Final properties are blocking overrides in derived classes
        /// </summary>
        public bool IsFinal
        {
            get
            {
                var prop = Object.RawData.GetPropertyNoCreate( ReflectionProp.Name );
                return (prop != null) ? prop.IsFinal : false;
            }
        }

        /// <summary>
        /// Is this an array property ? If so the result of the value resolve will be a list of elements not a single element
        /// Also, it means that the property view is castable to EditorPropertyViewArray (needed for additional actions)
        /// </summary>
        public bool IsArray { get { return ReflectionProp.IsArray && !IsArrayElement; } }

        /// <summary>
        /// Is this a property for an array element ?
        /// For such properties some additional actions are available
        /// </summary>
        public bool IsArrayElement { get { return ValueID != Guid.Empty; } }

        /// <summary>
        /// Is this property considered advanced ?
        /// If so this property will be displayed only when user switches the advanced view on
        /// </summary>
        public bool IsAdvanced { get { return ReflectionProp.IsAdvanced; } }

        /// <summary>
        /// Does this property contain inlined objects?
        /// </summary>
        public bool IsInlined { get { return ReflectionProp.IsInlined; } }

        /// <summary>
        /// Is this property optional? If so it can have no value defined AT ALL (in the whole object stack).
        /// </summary>
        public bool IsOptional { get { return ReflectionProp.IsOptional; } }

        /// <summary>
        /// Is this a read only property?
        /// </summary>
        public bool IsReadOnly { get { return ReflectionProp.IsReadOnly; } }

        /// <summary>
        /// Is this an editor only property?
        /// </summary>
        public bool IsEditorOnly { get { return ReflectionProp.IsEditorOnly; } }

        /// <summary>
        /// Is this an object pointing property?
        /// </summary>
        public bool IsObject { get { return (ReflectionType is Raw.ReflectionClass); } }

        /// <summary>
        /// Is this an enumeration property?
        /// </summary>
        public bool IsEnum { get { return (ReflectionType is Raw.ReflectionEnum); } }

        /// <summary>
        /// Initialize the property view, the value is able to refresh itself whenever needed (consistency tracking)
        /// Just use the DisplayValue/Value/ValueObjects functions normally
        /// For arrays you need to create sub-items, they can also track their state
        /// </summary>
        /// <param name="obj">Object view - provides the data</param>
        /// <param name="prop">Reflection property (gives us the type and the array flag)</param>
        /// <param name="valueId">In case of array elements, this indicated which array element is tracked by this property</param>
        public EditorPropertyView(EditorObjectView obj, Raw.ReflectionProperty prop)
        {
            Object = obj;
            ReflectionProp = prop;
            ValueID = Guid.Empty;

            _CachedIsWritable = true;
        }

        /// <summary>
        /// Create property wrapper for sub-element (array element)
        /// </summary>
        /// <param name="valueId">ValueID of the element to wrap</param>
        /// <returns></returns>
        public EditorPropertyView CreateElementProp(Guid valueId)
        {
            var ret = new EditorPropertyView(Object, ReflectionProp);
            ret.ValueID = valueId;
            ret.ParentProp = this;
            ret.EnsureDataConsistency();
            return ret;
        }
    }

}
